#pragma once 
#include <iostream>
#include <queue>
#include <pthread.h>
#include <unistd.h>
#include <ctime>
using namespace std;
#define NUM 20

template<class T>
class BlockQueue
{
    static const int defaultnum = NUM;
public:
    BlockQueue(int maxcap = defaultnum)
        :maxcap_(maxcap)
    {
        pthread_mutex_init(&mutex_,nullptr);
        pthread_cond_init(&c_cond_,nullptr);
        pthread_cond_init(&p_cond_,nullptr);
        low_water_=maxcap_/3;
        high_water_=(maxcap_*2)/3;
    }


    T pop()//--------消费
    {
        pthread_mutex_lock(&mutex_);
        while(q_.size()==0)//-------仓库没有资源,无法进行消费
        {
            pthread_cond_wait(&c_cond_,&mutex_);
        }
        T out = q_.front();
        q_.pop();
        //消费后,唤醒生产者生产
        // if(q_.size()<low_water_)
        // pthread_cond_signal(&p_cond_);
        pthread_cond_broadcast(&p_cond_);
        pthread_mutex_unlock(&mutex_);
        return out;
    }

    void push(const T& in)//-----生产
    {
        pthread_mutex_lock(&mutex_);
        while(q_.size()==maxcap_)//------仓库已满,无法进行生产
        {
            pthread_cond_wait(&p_cond_,&mutex_);
            //释放锁  + 排队
        }
        //队列没满 /  被唤醒  执行生产
        q_.push(in);        //------生产,需要确保仓库没满
        //生产后,唤醒消费者消费
        // if(q_.size()>high_water_)
        pthread_cond_signal(&c_cond_);
        pthread_mutex_unlock(&mutex_);
    }
  

    ~BlockQueue()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&c_cond_);
        pthread_cond_destroy(&p_cond_);
    }

private:
    queue<T> q_;                //共享资源
    int maxcap_;                // 为什么不用queue的size,极值?当到达极值就不放了
    pthread_mutex_t mutex_;     //锁
    pthread_cond_t c_cond_;        //消费者条件变量
    pthread_cond_t p_cond_;        //生产者条件变量
    //必须要有两条队伍

    //设置"水位线"---来控制生产一批,消费一批
    int low_water_;
    int high_water_;
};

